<?php

namespace App\Containers\AppSection\Profile\UI\API\Requests;

use App\Containers\AppSection\Ban\Traits\ProfilesBan;
use App\Containers\AppSection\Ban\Traits\UsersBan;
use App\Containers\AppSection\Questionnaire\Tasks\FindFieldByIdTask;
use App\Containers\AppSection\Questionnaire\Tasks\FindResponseByIdTask;
use App\Containers\AppSection\Questionnaire\Traits\UpdateQuestionnaireRequestTrait;
use App\Ship\Parents\Requests\Request;
use App\Ship\Rules\PhoneRule;
use App\Ship\Rules\ProhibitedRule;
use App\Ship\Traits\AccreditationStatusPermissionTrait;
use Carbon\Carbon;
use Illuminate\Validation\Rule;

class UpdateOuterProfileRequest extends Request
{
    use UpdateQuestionnaireRequestTrait;
    use AccreditationStatusPermissionTrait;
    use ProfilesBan;
    use UsersBan;

    /**
     * Define which Roles and/or Permissions has access to this request.
     */
    protected array $access = [
        'permissions' => '',
        'roles' => 'borrower|investor',
    ];

    /**
     * Id's that needs decoding before applying the validation rules.
     */
    protected array $decode = [
        //'id',
    ];

    /**
     * Defining the URL parameters (e.g, `/user/{id}`) allows applying
     * validation rules on them and allows accessing them like request data.
     */
    protected array $urlParameters = [
        //'id',
    ];

    /**
     * Get the validation rules that apply to the request.
     */
    public function rules(): array
    {
        $isDraft = $this->getInputByKey('is_draft', false);
        $required = $isDraft ? 'nullable' : 'required';

        $responses = $this->getInputByKey('responses', []);
        $responsesRules = [
            'responses' => ['bail', 'required', 'array', $this->responsesRule($this->profile()->legal_form->questionnaire->responses)]
        ];


        foreach ($responses as $key => $response) {
            $response2 = app(FindResponseByIdTask::class)->run($response['id']);
            $responsesRules = array_merge($responsesRules, [
                "responses.$key.id" => ['required', Rule::exists('questionnaire_responses', 'id')],
                "responses.$key.values" => ['bail', 'required', 'array', $this->valuesRule($response2->form->fields)],
            ]);

            $values = $response['values'];
            foreach ($values as &$v) {
                $v['field'] = app(FindFieldByIdTask::class)->run($v['field_id']);
            }

            foreach ($values as $key2 => $value) {
                $responsesRules = array_merge($responsesRules, [
                    "responses.$key.values.$key2.field_id" => ['bail', 'required', Rule::exists('questionnaire_fields', 'id')],
                    "responses.$key.values.$key2.person" => ['bail', 'required', 'numeric'],
                    "responses.$key.values.$key2" => ['bail', $this->valueRule($values, $value['field'], $isDraft)]
                ]);
            }
        }

        return array_merge($responsesRules, [
            'personal' => ['required'],
            'personal.fio' => [$required, 'max:100'],
            'personal.without_patronymic' => [$required, 'boolean'],
            'personal.phone' => [$required, new PhoneRule/*, Rule::unique('profiles', 'phone')->ignore($this->profile()->id)*/],
            'personal.phone_code' => ['nullable', 'digits:' . config('appSection-confirmation.code-length')],
            'personal.birth_date' => [$required, 'date_format:d.m.Y', 'before:' . Carbon::now()->subYears(18)->format('d.m.Y')],
            'personal.ogrnip' => $this->profile()->hasLegalForm('ie') ? [$required, 'regex:/^\d{15}$/i'] : [new ProhibitedRule],
            'personal.position' => [$this->profile()->hasLegalForm('entity') ? $required : new ProhibitedRule, 'max:200'],
            'personal.inn' => [$required, 'digits:' . ($this->profile()->hasLegalForm('entity') ? '10' : '12')],
            'personal.snils' => $this->user()->hasRole('borrower') ? [$required, 'digits:11'] : [new ProhibitedRule],
            'personal.birth_place' => [$required, 'max:200'],
            'personal.registration_address' => [$required, 'max:500'],
            'personal.address_matches' => $this->user()->hasRole('borrower') ? [$required, Rule::in([true, false])] : [new ProhibitedRule],
            'personal.residence_address' => $this->user()->hasRole('borrower') ? ['exclude_if:address_matches,true', $required, 'max:500'] : [new ProhibitedRule],

            'passport' => ['required'],
            'passport.serial_number' => [$required, 'regex:/^\d{4}-\d{6}$/i'],
            'passport.issue_date' => [$required, 'date_format:d.m.Y', 'before:' . date('Y-m-d')],
            'passport.department_code' => [$required, 'regex:/^\d{3}-\d{3}$/i'],
            'passport.issued_by' => [$required, 'max:300'],
            'passport.first_photo_id' => [$required, Rule::exists('files', 'id')->where(function ($query) {
                return $query->where('type', 'passport');
            })],
            'passport.second_photo_id' => [$required, Rule::exists('files', 'id')->where(function ($query) {
                return $query->where('type', 'passport');
            })],

            'company' => [$this->profile()->hasLegalForm('entity') ? 'required' : new ProhibitedRule],
            'company.name' => [$this->profile()->hasLegalForm('entity') ? $required : 'nullable', 'max:300'],
            'company.ogrn' => [$this->profile()->hasLegalForm('entity') ? $required : 'nullable', 'digits:13'],
            'company.inn' => [$this->profile()->hasLegalForm('entity') ? $required : 'nullable', 'digits:' . ($this->profile()->hasLegalForm('entity') ? '10' : '12')],
            'company.legal_address' => [$this->profile()->hasLegalForm('entity') ? $required : 'nullable', 'max:500'],
            'company.actual_address' => [$this->profile()->hasLegalForm('entity') ? $required : 'nullable', 'exclude_if:company.address_matches,true', 'max:500'],
            'company.address_matches' => [$this->profile()->hasLegalForm('entity') ? $required : 'nullable', Rule::in([true, false])],

            'documents' => ['array'],
            'documents.*' => [Rule::exists('files', 'id')->where(function ($query) {
                return $query->where('type', 'legal_form_documents');
            })],
        ]);
    }

    /**
     * Determine if the user is authorized to make this request.
     */
    public function authorize(): bool
    {
        return $this->check([
            'hasAccess',
            'profileIsNotRejected',
            'profileIsNotBanned',
            'userIsNotBanned'
        ]);
    }
}
